<template>
  <div class="container">
    <div class="app-container">
      <!-- 角色管理页面结构 -->
      <!-- 添加角色按钮 -->
      <div style="padding: 10px">
        <el-button type="primary" size="mini" @click="addRoleClick">添加角色</el-button>
      </div>
      <!-- 展示角色列表的表格 -->
      <el-table :data="roleList">
        <el-table-column prop="name" label="角色" align="center" width="200px">
          <!-- 利用作用域插槽，进行条件渲染 -->
          <template #default="{row}">
            <el-input v-if="row.isEdit" v-model="row.editRow.name" size="mini" />
            <span v-else>{{ row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="state" label="启用" align="center" width="200px">
          <template #default="{row}">
            <!-- 开 1；关 0 -->
            <el-switch v-if="row.isEdit" v-model="row.editRow.state" :active-value="1" :inactive-value="0" />
            <span v-else>{{ row.state === 1 ? '已启用' : row.state === 0 ? '未启用' : '无' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="description" label="描述" align="center">
          <template #default="{row}">
            <el-input v-if="row.isEdit" v-model="row.editRow.description" type="textarea" size="mini" />
            <span v-else>{{ row.description }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="{row}">
            <div v-if="row.isEdit">
              <el-button type="primary" size="mini" @click="editConfirmClick(row)">确定</el-button>
              <el-button size="mini" @click="row.isEdit=false">取消</el-button>
            </div>
            <div v-else>
              <el-button type="text" size="mini">分配权限</el-button>
              <el-button type="text" size="mini" @click="editClick(row)">编辑</el-button>
              <el-button type="text" size="mini">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!-- 角色分页器 -->
      <el-row style="height: 60px" type="flex" justify="end" align="middle">
        <!-- 分页器的三个属性：current-page、page-size、total跟服务端数据绑定的，值需要根据接口文档编写 -->
        <el-pagination
          layout="prev, pager, next"
          :current-page="pageParams.page"
          :page-size="pageParams.pagesize"
          :total="pageParams.total"
          @current-change="handlecurrentChange"
        />
      </el-row>
    </div>
    <!-- 放置弹层 -->
    <el-dialog width="500px" title="新增角色" :visible.sync="showDialog" @close="cancelClick">
      <!-- 新增角色表单 -->
      <el-form ref="roleForm" :model="roleForm" :rules="roleRules" label-width="100px">
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="roleForm.name" size="mini" style="width: 300px" />
        </el-form-item>
        <!-- 如果该字段不需要校验，该字段的prop属性可以不设置 -->
        <!-- 但是，如果有重置表单的需求，则无论该字段是否需要校验，都要设置prop属性 -->
        <el-form-item label="启用" prop="state">
          <!-- active-value设置打开开关时的值，inactive-value设置关闭开关时的值 -->
          <el-switch v-model="roleForm.state" :active-value="1" :inactive-value="0" size="mini" />
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input v-model="roleForm.description" type="textarea" :rows="3" size="mini" style="width: 300px" />
        </el-form-item>
        <el-form-item>
          <el-row style="width: 300px" type="flex" justify="center">
            <el-button size="mini" type="primary" @click="confirmClick">确定</el-button>
            <el-button size="mini" @click="cancelClick">取消</el-button>
          </el-row>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>
<script>
import { addRoleAPI, getRolesAPI, updateRoleAPI } from '@/api/role'
export default {
  name: 'Role',
  data() {
    return {
      // 角色列表数据
      roleList: [],
      // 分页查询参数
      pageParams: {
        page: 1, // 当前页
        pagesize: 5, // 每页记录条数
        total: 0 // 记录总条数
      },
      showDialog: false, // 控制弹层显示和隐藏
      // 角色表单数据对象，根据《新增角色》的接口文档编写
      roleForm: {
        name: '', // 角色名称
        description: '', // 角色描述
        state: 1 // 角色启用状态：1 表示已启用 0 表示未启用，默认是启用的
      },
      // 校验规则
      roleRules: {
        name: [
          { required: true, message: '角色名称不能为空', trigger: 'blur' }
        ],
        description: [
          { required: true, message: '角色描述不能为空', trigger: 'blur' }
        ]
        // state: [] // 不需要校验的，因为el-switch无论是开还是关都是有值
      }
    }
  },
  created() {
    this.getRoleList()
  },
  methods: {
    // 点击编辑的确定按钮
    async editConfirmClick(row) {
      // 检查角色名称和描述是否为空
      if (row.editRow.name && row.editRow.description) {
        // 如果通过校验，调用更新角色的接口方法
        // updateRoleAPI({
        //   name: row.editRow.name,
        //   description: row.editRow.description,
        //   state: row.editRow.state,
        //   id: row.id
        // })
        await updateRoleAPI({ ...row.editRow, id: row.id })
        // 更新角色成功，友好提示用户：修改角色成功
        this.$message.success('修改角色成功')
        // 更新角色数据：不能重新获取角色列表，因为当前是行内编辑，可以同时编辑多个，编辑谁就针对的更新谁
        // 将编辑之后的editRow的数据同步到row用于编辑之后的显示
        // 以下代码的赋值无错，仅仅是eslint代码校验中的**误判**，可以选择快速修复
        // row.name = row.editRow.name

        // 如果不想使用快速修复：Object.assign(目标对象, 值)
        Object.assign(row, {
          // 这里适合使用展开运算符，因为editRow的字段比row少，不会出现多余的字段
          ...row.editRow,
          // 由于editRow中，没有isEdit，所以使用展开运算符时，无法给row设置编辑的标记
          isEdit: false // 退出编辑状态
        })
      } else {
        this.$message.warning('角色名称和描述不能为空')
      }
    },
    // 点击编辑按钮：点击了哪一行就给那一行设置为编辑状态
    editClick(row) {
      row.isEdit = true
      // 更新缓存数据：避免editRow中未编辑完的数据污染了初始表单
      // 把row中的数据更新到editRow
      row.editRow.name = row.name
      row.editRow.description = row.description
      row.editRow.state = row.state

      // 由于editRow对象只需要row对象的部分属性和值，所以不需要展开
      // row.editRow = {
      //   ...row
      // }
    },
    // 点击弹层确定按钮
    confirmClick() {
      // 角色表单整体校验
      this.$refs.roleForm.validate(async(isOK) => {
        if (isOK) {
          // 如果校验通过，调用新增角色接口方法
          await addRoleAPI(this.roleForm)
          // 新增角色成功，友好提示用户，新增角色成功
          this.$message.success('新增角色成功')
          // 重新刷新角色列表当前页面
          this.getRoleList()
          // 重置表单 + 关闭弹层
          this.cancelClick()
        }
      })
    },
    // 重置表单 + 关闭弹层
    cancelClick() {
      this.$refs.roleForm.resetFields()
      this.showDialog = false
    },
    // 点击添加角色按钮：显示弹层
    addRoleClick() {
      this.showDialog = true
    },
    // 切换页面时调用的
    handlecurrentChange(currentPage) {
      // 更换当前用户点击的页码
      this.pageParams.page = currentPage
      // 使用新的页码发起请求获取对应页的角色列表数据
      this.getRoleList()
    },
    // 专门封装一个获取并展示角色列表数据的方法，方便复用
    async getRoleList() {
      // 调用角色列表接口
      const { rows, total } = await getRolesAPI(this.pageParams)
      this.roleList = rows
      this.pageParams.total = total

      // 给每一行的数据对象设置编辑状态的标记，标记是否是编辑状态
      this.roleList.forEach(item => {
        // 经验：利用JS的语法动态添加的属性，都是非响应式的，数据即使变化了，也不会影响视图
        // item.isEdit = false
        // 解决：利用Vue的语法，动态的给对象设置响应式的属性
        // this.$set(目标对象, "属性", 属性初始值)
        this.$set(item, 'isEdit', false)
        // 动态的给每一行的数据对象添加响应式属性editRow（备份的数据，做数据隔离）
        // 类似于做弹层编辑时，回显编辑数据，做的发请求得到待编辑数据的动作
        this.$set(item, 'editRow', {
          name: item.name,
          description: item.description,
          state: item.state
          // 由于editRow对象只需要item对象的部分属性和值，所以不需要展开
          // ...item
        })
      })
      console.log(this.roleList)
    }
  }
}
</script>
